package xm.net
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.net.URLRequestMethod;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	
	
	/**
	 * <br> 클래스 설명 : </br>
	 * @author 김정환
	 */	
	public class MultipartUploader extends EventDispatcher
	{
		
		//-----------------------------------------------------------------------------------
		// public vars
		//-----------------------------------------------------------------------------------
		
		/**
		 * url 
		 */		
		public var url : String = "";
		
		
		/**
		 * formData ( multipart용 ) 
		 */		
		public var formData : FormData;
		
		
		
		
		//-----------------------------------------------------------------------------------
		// protected / internal vars
		//-----------------------------------------------------------------------------------
		
		/**
		 * urlRequest 
		 */		
		protected var urlRequest : URLRequest = new URLRequest();
		
		
		//-----------------------------------------------------------------------------------
		// private vars
		//-----------------------------------------------------------------------------------
		
		
		private var dicCompleteHandler : Dictionary = new Dictionary( true );
		private var dicProgressHandler : Dictionary = new Dictionary( true );
		private var dicErrorHandler : Dictionary = new Dictionary( true );
		
		
		//-----------------------------------------------------------------------------------
		// public functions
		//-----------------------------------------------------------------------------------
		
		/**
		 * constructor 
		 */	
		public function MultipartUploader( url : String = "", formData : FormData = null )
		{
			
			if( url != "" )
			{
				this.url = url;
			}
			
			if( formData != null )
			{
				this.formData = formData;
			}
		}
		
		
		/**
		 * 업로드 시작.
		 * @param completeHandler : 인자로 MultipartData 를 받아야 함.
		 * @param errorHandler : 인자로 MultipartData 를 받아야 함.
		 * @param progressHandler : 인자로 MultipartData 를 받아야 함.
		 */		
		public function upload( completeHandler : Function = null, errorHandler : Function = null, progressHandler : Function = null ):void
		{
			if( url == "" )
			{
				throw new Error( "MultipartUploader upload - URL 정보가 없습니다." );
			}
			
			if( formData == null )
			{
				throw new Error( "MultipartUploader upload - formData 정보가 없습니다. " );
			}
			
			
			urlRequest.url = url;
			urlRequest.method = URLRequestMethod.POST;
			urlRequest.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );
			urlRequest.requestHeaders.push( new URLRequestHeader( 'Content-Type', 'multipart/form-data; boundary=' + formData.main_boundary ) );
			urlRequest.data = formData.getPostData();
			
			
			
			var ldr : URLLoader = new URLLoader();
			dicCompleteHandler[ ldr ] = completeHandler;
			dicErrorHandler[ ldr ] = errorHandler;
			dicProgressHandler[ ldr ] = progressHandler;
			
			ldr.dataFormat = URLLoaderDataFormat.BINARY;
			ldr.addEventListener(Event.COMPLETE, onFormDataLoadComplete );
			ldr.addEventListener(IOErrorEvent.IO_ERROR, onIOE );
			ldr.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError );
			ldr.addEventListener(ProgressEvent.PROGRESS, onProgress );
			ldr.load( urlRequest );
			
		}
		
		
		
		
		/**
		 * destroy
		 */		
		public function destroy():void
		{
			url = "";
			urlRequest = null;
			formData = null;
			
			dicCompleteHandler = null;
			dicErrorHandler = null;
			dicProgressHandler = null;
		}
		
		//-----------------------------------------------------------------------------------
		// setter / getter
		//-----------------------------------------------------------------------------------
		
		
		
		//-----------------------------------------------------------------------------------
		// protected functions
		//-----------------------------------------------------------------------------------
		
		
		
		//-----------------------------------------------------------------------------------
		// internal functions
		//-----------------------------------------------------------------------------------
		
		
		
		
		//-----------------------------------------------------------------------------------
		// private functions
		//-----------------------------------------------------------------------------------
		
		
		
		private function deleteHandler( ldr : URLLoader ):void
		{
			delete dicCompleteHandler[ ldr ];
			delete dicProgressHandler[ ldr ];
			delete dicErrorHandler[ ldr ];
		}
		
		//-----------------------------------------------------------------------------------
		// event handler
		//-----------------------------------------------------------------------------------
		
		
		
		/**
		 * @param e
		 */		
		protected function onSecurityError(e:SecurityErrorEvent):void
		{
			var data : MultipartData = new MultipartData();
			data.target = this;
			data.type = e.type;
			data.errorID = e.errorID;
			data.errorMessage = e.text;
			
			if( dicErrorHandler[ e.currentTarget ] != null ) dicErrorHandler[ e.currentTarget ](data);
			deleteHandler( e.currentTarget as URLLoader );
		}
		
		/**
		 * @param e
		 */		
		protected function onIOE(e:IOErrorEvent):void
		{
			var data : MultipartData = new MultipartData();
			data.target = this;
			data.type = e.type;
			data.errorID = e.errorID;
			data.errorMessage = e.text;
			
			if( dicErrorHandler[ e.currentTarget ] != null ) dicErrorHandler[ e.currentTarget ](data);
			deleteHandler( e.currentTarget as URLLoader );
		}
		
		/**
		 * @param e
		 */		
		protected function onProgress(e:ProgressEvent):void
		{
			var data : MultipartData = new MultipartData();
			data.target = this;
			data.type = e.type;
			data.byteLoaded = e.bytesLoaded;
			data.byteTotal = e.bytesTotal;
			
			if( dicProgressHandler[ e.currentTarget ] != null ) dicProgressHandler[ e.currentTarget ](data);
		}
		
		/**
		 * @param e
		 */		
		protected function onFormDataLoadComplete(e:Event):void
		{
			var data : MultipartData = new MultipartData();
			data.target = this;
			data.type = e.type;
			
			var bytes : ByteArray = e.currentTarget.data as ByteArray;
			var i:int = 0;
			var len : int = bytes.length;
			bytes.position = 0;
			data.data = bytes.readUTFBytes(bytes.length);
			
			
			if( dicCompleteHandler[ e.currentTarget ] != null ) dicCompleteHandler[ e.currentTarget ](data);
			deleteHandler( e.currentTarget as URLLoader );
		}
		
		
		
	}
}



